#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#include <libutils2/boot_time.h>
#include <utils/avilib.h>
#include "debug/debug.h"
#include "media_ipc_msg.h"
#include "record_avi.h"

#include "media.h"

static struct st_record record = {
    .h264_video_encoder = NULL,
    .avi.avi_writer = NULL,
};

int media_record_start(const char* record_dir, const char* name, int width, int height)
{
    int ret = -1;
    char file_name[MAX_RECORD_FILE_NAME_LENGHT] = { 0 };
	char mkdir_cmd[100] = "mkdir ";
	
	strcat(mkdir_cmd, record_dir);
	strcat(mkdir_cmd, " -p");
	system(mkdir_cmd);

    if (record.avi.avi_writer == NULL)
    {
        ret = media_encoder_open(width, height);
        if (ret < 0)
        {
            print_warning("h264 encoder open faile.");
            return ret;
        }

		sprintf(file_name, "%s/%s", record_dir, name);
        record.avi.avi_writer = AVI_open_output_file(file_name);;
        if (record.avi.avi_writer == NULL)
        {
            print_error("avi open output file  %s faild. %s", file_name, strerror(errno));
            return ret;
        }

		record.frame_cnt = 0;
		record.width = width;
		record.height = height;
		record.end_time = 0;
		record.duration = 0;
		record.start_time =0;

        return 0;
    }

    return ret;
}

int do_media_record(struct video_frame* frame)
{
    int ret = -1;
    struct media_packet* media_pkt;
    struct hw_jpeg_video_encoder_param jpeg_param;
    struct video_encoder* jpeg_video_encoder = NULL;

    assert(record.h264_video_encoder);
    assert(frame);
    
    if (record.avi.avi_writer == NULL)
    {
        print_warning("media record didn't start.");
        return ret;
    }

	if(record.frame_cnt == 0)
	{
    	hw_jpeg_encoder_init_default_param(&jpeg_param, frame->width, frame->height);
		
		jpeg_video_encoder =  video_encoder_open(&jpeg_param.param);
		if(jpeg_video_encoder != NULL)
		{
			video_encoder_write_frame(jpeg_video_encoder, frame);
   			video_encoder_get_packet(jpeg_video_encoder, &media_pkt);
			AVI_write_audio(record.avi.avi_writer, media_pkt->data, media_pkt->size);
		    media_packet_put(media_pkt);
			video_encoder_close(jpeg_video_encoder);
		}
	}

    ret = video_encoder_write_frame(record.h264_video_encoder, frame);
    if (ret < 0)
    {
        print_error("video encoder failed.");
        return ret;
    }

    ret = video_encoder_get_packet(record.h264_video_encoder, &media_pkt);
    if (ret < 0)
    {
        print_error("video encoder get packet failed.");
        return ret;
    }
    
    ret = AVI_write_frame(record.avi.avi_writer, media_pkt->data, media_pkt->size);
     if( ret != 0 )
     {
          print_error("fwrite error %d  unequal %d!", ret , media_pkt->size);
     }  
    if(record.frame_cnt == 0)
    {
    	record.start_time = boot_time_usecs();
    }
    else
    {
		record.end_time = boot_time_usecs();
		if(record.end_time > record.start_time)
        {
            record.duration = record.end_time - record.start_time;
            ack_record_duration(record.duration / 1000000);
        }
    }

    media_packet_put(media_pkt);
	record.frame_cnt++;
     return 0;
}

void media_record_stop(void)
{
	double fps = 0;

    if (record.avi.avi_writer != NULL)
    {
		if(record.end_time > record.start_time)
		{
			record.end_time -= record.start_time;
			fps = ((double)(record.frame_cnt * 1000000.0)) / record.end_time;
		}
		else
			record.end_time = 0;
         print_info("record.frame_cnt %llu  start time %llu  end time %llu",record.frame_cnt, record.start_time, record.end_time);
        print_info("video fps %f\n", fps );
        AVI_set_video(record.avi.avi_writer, record.width, record.height, fps, "H264");

        AVI_close(record.avi.avi_writer);
        record.avi.avi_writer = NULL;
    }

    media_encoder_close();
}

int media_encoder_open(int width, int height)
{
    int ret = -1;

    if (record.h264_video_encoder != NULL)
    {
        print_warning("h264 video encoer was opened, try to close is first.");
        return ret;
    }

    hw_h264_encoder_init_default_param(&record.h264_param, width, height);

    record.h264_video_encoder = video_encoder_open(&record.h264_param.param);
    if (record.h264_video_encoder == NULL)
    {
        print_error("h264 video encoder open failed.");
        return ret;
    }

	return 0;
}

void media_encoder_close(void)
{
    if (record.h264_video_encoder != NULL)
    {
		video_encoder_close(record.h264_video_encoder);
		record.h264_video_encoder = NULL;
    }
}